package com.icongyou.enterprise.course_detail.integration;

import com.icongyou.enterprise.course_detail.entity.AssignmentEntity;
import com.icongyou.enterprise.course_detail.entity.AssignmentRankEntity;
import com.icongyou.enterprise.course_detail.entity.vo.CourseDetailVO;
import com.icongyou.enterprise.course_detail.mapper.CourseDetailMapper;
import com.icongyou.enterprise.course_detail.service.CourseDetailService;
import com.icongyou.enterprise.data_aggregation.entity.*;
import com.icongyou.enterprise.data_aggregation.service.DataAggregationService;
import com.icongyou.enterprise.talent_marking.service.HighPotentialSubmissionService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;

/**
 * 课程详情模块集成测试
 * 测试完整的业务流程和各组件协作
 */
@SpringBootTest
@DisplayName("课程详情模块集成测试")
public class CourseDetailIntegrationTest {

    @Autowired
    private CourseDetailService courseDetailService;

    @MockBean
    private DataAggregationService dataAggregationService;

    @MockBean
    private CourseDetailMapper courseDetailMapper;

    @MockBean
    private HighPotentialSubmissionService highPotentialSubmissionService;

    private static final String TEST_STUDENT_ID = "660e8400-e29b-41d4-a716-446655440101";
    private static final String TEST_COURSE_ID = "aa0e8400-e29b-41d4-a716-446655440501";

    @BeforeEach
    void setUp() {
        setupMockData();
    }

    @Test
    @DisplayName("集成测试1: 获取完整课程详情 - 包含个人和团队任务")
    void testGetCompleteCourseDetail() {
        // 执行
        CourseDetailVO result = courseDetailService.getCourseDetail(TEST_STUDENT_ID, TEST_COURSE_ID);

        // 验证
        assertNotNull(result, "课程详情不应为null");
        assertEquals(TEST_COURSE_ID, result.getCourseId(), "课程ID应匹配");
        assertEquals(TEST_STUDENT_ID, result.getStudentId(), "学生ID应匹配");
        assertEquals("软件工程实践", result.getCourseName(), "课程名称应匹配");
        assertEquals("张三", result.getStudentName(), "学生姓名应匹配");
        
        // 验证总分和排名
        assertEquals(85.5, result.getTotalScore(), 0.01, "总分应匹配");
        assertEquals(5, result.getCourseRank(), "课程排名应匹配");

        // 验证任务列表
        assertNotNull(result.getAssignments(), "任务列表不应为null");
        assertEquals(3, result.getAssignments().size(), "应有3个任务");

        // 验证排名趋势
        assertNotNull(result.getRankTrend(), "排名趋势不应为null");
        assertTrue(result.getRankTrend().size() > 0, "排名趋势应有数据");

        // 验证团队贡献度
        assertNotNull(result.getTeamContribution(), "团队贡献度不应为null");
    }

    @Test
    @DisplayName("集成测试2: 个人任务处理 - 验证贡献度和得分计算")
    void testPersonalAssignmentProcessing() {
        CourseDetailVO result = courseDetailService.getCourseDetail(TEST_STUDENT_ID, TEST_COURSE_ID);

        // 找到个人任务
        var personalTask = result.getAssignments().stream()
                .filter(a -> a.getAssignmentType() == 0)
                .findFirst()
                .orElse(null);

        assertNotNull(personalTask, "应该有个人任务");
        assertEquals("第一周个人作业：环境搭建", personalTask.getAssignmentName());
        assertEquals(0, new BigDecimal("100").compareTo(personalTask.getContributionRate()), "个人任务贡献度应为100%");
        assertEquals(0, new BigDecimal("88.50").compareTo(personalTask.getScore()), "得分应为88.50");
        assertFalse(personalTask.getIsLate(), "未逾期");
    }

    @Test
    @DisplayName("集成测试3: 团队任务处理 - 验证贡献度分配")
    void testTeamAssignmentProcessing() {
        CourseDetailVO result = courseDetailService.getCourseDetail(TEST_STUDENT_ID, TEST_COURSE_ID);

        // 找到团队任务
        var teamTasks = result.getAssignments().stream()
                .filter(a -> a.getAssignmentType() == 1)
                .toList();

        assertFalse(teamTasks.isEmpty(), "应该有团队任务");
        
        // 验证第一个团队任务
        var firstTeamTask = teamTasks.get(0);
        assertEquals("第二周团队作业：需求分析", firstTeamTask.getAssignmentName());
        assertEquals(0, new BigDecimal("25.00").compareTo(firstTeamTask.getContributionRate()), "该学生贡献度为25%");
        
        // 验证得分计算：90 * 25% = 22.50
        assertEquals(0, new BigDecimal("22.50").compareTo(firstTeamTask.getScore()), "团队任务得分应按贡献度计算");
    }

    @Test
    @DisplayName("集成测试4: 排名变化趋势计算")
    void testRankTrendCalculation() {
        CourseDetailVO result = courseDetailService.getCourseDetail(TEST_STUDENT_ID, TEST_COURSE_ID);

        var rankTrend = result.getRankTrend();
        assertNotNull(rankTrend);
        assertEquals(3, rankTrend.size(), "应有3个任务的排名数据");

        // 验证排名趋势数据完整性
        rankTrend.forEach(point -> {
            assertNotNull(point.getAssignmentId(), "任务ID不应为null");
            assertNotNull(point.getAssignmentName(), "任务名称不应为null");
            assertNotNull(point.getRank(), "排名不应为null");
            assertTrue(point.getTotalParticipants() > 0, "参与人数应大于0");
        });
    }

    @Test
    @DisplayName("集成测试5: 团队贡献度统计")
    void testTeamContributionStatistics() {
        CourseDetailVO result = courseDetailService.getCourseDetail(TEST_STUDENT_ID, TEST_COURSE_ID);

        var teamContribution = result.getTeamContribution();
        assertNotNull(teamContribution);
        
        // 验证团队贡献度数据
        assertTrue(teamContribution.getTeamContribution().doubleValue() >= 0, "团队贡献度应大于等于0");
        assertEquals(1, teamContribution.getTeamTaskCount(), "应有1个团队任务");
        
        // 验证成员贡献度列表
        var memberContributions = teamContribution.getMemberContributions();
        assertNotNull(memberContributions);
        assertFalse(memberContributions.isEmpty(), "成员贡献度列表不应为空");
        
        // 验证当前学生在列表中
        boolean hasCurrentStudent = memberContributions.stream()
                .anyMatch(m -> m.getIsCurrentStudent() && TEST_STUDENT_ID.equals(m.getStudentId()));
        assertTrue(hasCurrentStudent, "成员列表应包含当前学生");
    }

    @Test
    @DisplayName("集成测试6: 高潜力成果标记")
    void testHighPotentialAchievementMarking() {
        CourseDetailVO result = courseDetailService.getCourseDetail(TEST_STUDENT_ID, TEST_COURSE_ID);

        // 检查是否有任务包含高潜力成果
        boolean hasHighPotential = result.getAssignments().stream()
                .flatMap(a -> a.getCoreAchievements().stream())
                .anyMatch(achievement -> achievement.getIsHighPotential());

        assertTrue(hasHighPotential, "应至少有一个高潜力成果");
    }

    @Test
    @DisplayName("集成测试7: 逾期任务处理")
    void testLateSubmissionHandling() {
        CourseDetailVO result = courseDetailService.getCourseDetail(TEST_STUDENT_ID, TEST_COURSE_ID);

        // 检查逾期任务
        var lateTasks = result.getAssignments().stream()
                .filter(a -> a.getIsLate() != null && a.getIsLate())
                .toList();

        assertEquals(1, lateTasks.size(), "应有1个逾期任务");
        assertEquals("第三周个人作业：代码实现", lateTasks.get(0).getAssignmentName());
    }

    @Test
    @DisplayName("集成测试8: 教师评语获取")
    void testTeacherComments() {
        CourseDetailVO result = courseDetailService.getCourseDetail(TEST_STUDENT_ID, TEST_COURSE_ID);

        // 检查有评语的任务
        var tasksWithComments = result.getAssignments().stream()
                .filter(a -> a.getTeacherComment() != null && !a.getTeacherComment().isEmpty())
                .toList();

        assertFalse(tasksWithComments.isEmpty(), "应至少有一个任务有教师评语");
    }

    /**
     * 设置Mock数据
     */
    private void setupMockData() {
        // Mock课程信息
        CourseEntity course = new CourseEntity();
        course.setCourseId(TEST_COURSE_ID);
        course.setCourseName("软件工程实践");
        when(dataAggregationService.getCourseById(TEST_COURSE_ID)).thenReturn(course);

        // Mock学生信息
        UserEntity student = new UserEntity();
        student.setId(TEST_STUDENT_ID);
        student.setRealName("张三");
        when(dataAggregationService.getStudentById(TEST_STUDENT_ID)).thenReturn(student);

        // Mock课程进度
        CourseProgressEntity progress = new CourseProgressEntity();
        progress.setTotalScore(new BigDecimal("85.5"));
        progress.setRanking(5);
        when(dataAggregationService.getStudentCourseProgress(TEST_STUDENT_ID, TEST_COURSE_ID)).thenReturn(progress);

        // Mock任务列表（1个人 + 2团队）
        List<AssignmentEntity> assignments = new ArrayList<>();
        
        // 个人任务
        AssignmentEntity personalAssignment = new AssignmentEntity();
        personalAssignment.setAssignmentId("ee0e8400-e29b-41d4-a716-446655440901");
        personalAssignment.setAssignmentName("第一周个人作业：环境搭建");
        personalAssignment.setAssignmentType(0);
        personalAssignment.setStartTime(LocalDateTime.now().minusDays(10));
        assignments.add(personalAssignment);

        // 团队任务1
        AssignmentEntity teamAssignment1 = new AssignmentEntity();
        teamAssignment1.setAssignmentId("ee0e8400-e29b-41d4-a716-446655440902");
        teamAssignment1.setAssignmentName("第二周团队作业：需求分析");
        teamAssignment1.setAssignmentType(1);
        teamAssignment1.setStartTime(LocalDateTime.now().minusDays(8));
        assignments.add(teamAssignment1);

        // 团队任务2
        AssignmentEntity teamAssignment2 = new AssignmentEntity();
        teamAssignment2.setAssignmentId("ee0e8400-e29b-41d4-a716-446655440903");
        teamAssignment2.setAssignmentName("第三周个人作业：代码实现");
        teamAssignment2.setAssignmentType(0);
        teamAssignment2.setStartTime(LocalDateTime.now().minusDays(5));
        assignments.add(teamAssignment2);

        when(courseDetailMapper.getStudentAssignmentsByCourse(TEST_STUDENT_ID, TEST_COURSE_ID))
                .thenReturn(assignments);

        // Mock提交记录
        setupMockSubmissions();

        // Mock成绩
        setupMockGrades();

        // Mock排名
        setupMockRankings();

        // Mock高潜力标记
        when(highPotentialSubmissionService.isSubmissionMarked(anyString(), anyString()))
                .thenAnswer(inv -> {
                    String submissionId = inv.getArgument(1);
                    return "ff0e8400-e29b-41d4-a716-446655441001".equals(submissionId); // 只有第一个提交被标记为高潜力
                });

        // Mock assignment_students 数据
        when(dataAggregationService.getStudentAssignmentScore(TEST_STUDENT_ID, TEST_COURSE_ID))
                .thenReturn(new ArrayList<>());
    }

    private void setupMockSubmissions() {
        List<SubmissionEntity> submissions = new ArrayList<>();

        // 个人任务提交
        SubmissionEntity personalSubmission = new SubmissionEntity();
        personalSubmission.setSubmissionId("ff0e8400-e29b-41d4-a716-446655441001");
        personalSubmission.setAssignmentId("ee0e8400-e29b-41d4-a716-446655440901");
        personalSubmission.setStudentId(TEST_STUDENT_ID);
        personalSubmission.setSubmissionTime(LocalDateTime.now().minusDays(9));
        personalSubmission.setIsLate(0);
        personalSubmission.setContentUrl("https://example.com/submissions/sub001.zip");
        personalSubmission.setLikeCount(5);
        personalSubmission.setFavoriteCount(2);
        submissions.add(personalSubmission);

        // 团队任务1提交（包含贡献度）
        SubmissionEntity teamSubmission1 = new SubmissionEntity();
        teamSubmission1.setSubmissionId("ff0e8400-e29b-41d4-a716-446655441005");
        teamSubmission1.setAssignmentId("ee0e8400-e29b-41d4-a716-446655440902");
        teamSubmission1.setStudentId("660e8400-e29b-41d4-a716-446655440105");
        teamSubmission1.setTeamId("cc0e8400-e29b-41d4-a716-446655440701");
        teamSubmission1.setSubmissionTime(LocalDateTime.now().minusDays(7));
        teamSubmission1.setIsLate(0);
        
        // 设置贡献度
        List<SubmissionEntity.ContributionItem> contributions1 = new ArrayList<>();
        SubmissionEntity.ContributionItem item1 = new SubmissionEntity.ContributionItem();
        item1.setStudentId(TEST_STUDENT_ID);
        item1.setRate(new BigDecimal("25.00"));
        contributions1.add(item1);
        
        SubmissionEntity.ContributionItem item2 = new SubmissionEntity.ContributionItem();
        item2.setStudentId("660e8400-e29b-41d4-a716-446655440105");
        item2.setRate(new BigDecimal("30.00"));
        contributions1.add(item2);
        
        teamSubmission1.setContributionRate(contributions1);
        submissions.add(teamSubmission1);

        // 团队任务2提交（週期）
        SubmissionEntity teamSubmission2 = new SubmissionEntity();
        teamSubmission2.setSubmissionId("ff0e8400-e29b-41d4-a716-446655441006");
        teamSubmission2.setAssignmentId("ee0e8400-e29b-41d4-a716-446655440903");
        teamSubmission2.setStudentId(TEST_STUDENT_ID);
        teamSubmission2.setTeamId(null);
        teamSubmission2.setSubmissionTime(LocalDateTime.now().minusDays(4));
        teamSubmission2.setIsLate(1); // 週期
        
        List<SubmissionEntity.ContributionItem> contributions2 = new ArrayList<>();
        SubmissionEntity.ContributionItem item3 = new SubmissionEntity.ContributionItem();
        item3.setStudentId(TEST_STUDENT_ID);
        item3.setRate(new BigDecimal("100.00"));
        contributions2.add(item3);
        
        SubmissionEntity.ContributionItem item4 = new SubmissionEntity.ContributionItem();
        item4.setStudentId("20210003");
        item4.setRate(new BigDecimal("65.00"));
        contributions2.add(item4);
        
        teamSubmission2.setContributionRate(contributions2);
        submissions.add(teamSubmission2);

        when(dataAggregationService.getStudentSubmissionsByCourse(TEST_STUDENT_ID, TEST_COURSE_ID))
                .thenReturn(submissions);
    }

    private void setupMockGrades() {
        // 个人任务成绩
        GradeEntity grade1 = new GradeEntity();
        grade1.setGradeId("110e8400-e29b-41d4-a716-446655441101");
        grade1.setSubmissionId("ff0e8400-e29b-41d4-a716-446655441001");
        grade1.setFinalScore(new BigDecimal("88.50"));
        grade1.setTextComment("环境搭建完整，文档规范");
        when(dataAggregationService.getStudentGrade("ff0e8400-e29b-41d4-a716-446655441001"))
                .thenReturn(Collections.singletonList(grade1));

        // 团队任务1成绩
        GradeEntity grade2 = new GradeEntity();
        grade2.setGradeId("110e8400-e29b-41d4-a716-446655441102");
        grade2.setSubmissionId("ff0e8400-e29b-41d4-a716-446655441005");
        grade2.setFinalScore(new BigDecimal("90"));
        grade2.setTextComment("团队协作良好");
        when(dataAggregationService.getStudentGrade("ff0e8400-e29b-41d4-a716-446655441005"))
                .thenReturn(Collections.singletonList(grade2));

        // 团队任务2成绩
        GradeEntity grade3 = new GradeEntity();
        grade3.setGradeId("110e8400-e29b-41d4-a716-446655441103");
        grade3.setSubmissionId("ff0e8400-e29b-41d4-a716-446655441006");
        grade3.setFinalScore(new BigDecimal("75"));
        grade3.setTextComment("週期提交，但质量尚可");
        when(dataAggregationService.getStudentGrade("ff0e8400-e29b-41d4-a716-446655441006"))
                .thenReturn(Collections.singletonList(grade3));
    }

    private void setupMockRankings() {
        // Mock任务排名
        AssignmentRankEntity rank1 = new AssignmentRankEntity();
        rank1.setAssignmentId("ee0e8400-e29b-41d4-a716-446655440901");
        rank1.setStudentId(TEST_STUDENT_ID);
        rank1.setRank(3);
        when(courseDetailMapper.getStudentAssignmentRank("ee0e8400-e29b-41d4-a716-446655440901", TEST_STUDENT_ID))
                .thenReturn(rank1);

        AssignmentRankEntity rank2 = new AssignmentRankEntity();
        rank2.setAssignmentId("ee0e8400-e29b-41d4-a716-446655440902");
        rank2.setStudentId(TEST_STUDENT_ID);
        rank2.setRank(8);
        when(courseDetailMapper.getStudentAssignmentRank("ee0e8400-e29b-41d4-a716-446655440902", TEST_STUDENT_ID))
                .thenReturn(rank2);

        AssignmentRankEntity rank3 = new AssignmentRankEntity();
        rank3.setAssignmentId("ee0e8400-e29b-41d4-a716-446655440903");
        rank3.setStudentId(TEST_STUDENT_ID);
        rank3.setRank(12);
        when(courseDetailMapper.getStudentAssignmentRank("ee0e8400-e29b-41d4-a716-446655440903", TEST_STUDENT_ID))
                .thenReturn(rank3);

        // Mock排名列表（用于计算总参与人数）
        List<AssignmentRankEntity> rankings = new ArrayList<>();
        for (int i = 1; i <= 30; i++) {
            AssignmentRankEntity r = new AssignmentRankEntity();
            r.setStudentId("student" + i);
            r.setRank(i);
            rankings.add(r);
        }
        when(courseDetailMapper.getAssignmentRankings(anyString())).thenReturn(rankings);
    }
}
